﻿#include "myJsonCpp.h"

#include <sstream>

Json::Json():m_type(Type::json_null)
{

}

Json::Json(bool value):m_type(Type::json_bool)
{
	m_value.m_bool = value;
}

Json::Json(int value):m_type(Type::json_int)
{
	m_value.m_int = value;
}

Json::Json(double value):m_type(Type::json_double)
{
	m_value.m_double = value;
}

Json::Json(const char* value):m_type(Type::json_string)
{
	m_value.m_string = new std::string(value);
}

Json::Json(const std::string& value):m_type(Type::json_string)
{
	m_value.m_string = new std::string(value);
}

Json::Json(Type type):m_type(type)
{
	switch (m_type)
	{
	case Json::Type::json_null:
		break;
	case Json::Type::json_bool:
		m_value.m_bool = false;
		break;
	case Json::Type::json_int:
		m_value.m_int = 0;
		break;
	case Json::Type::json_double:
		m_value.m_double = 0.0;
		break;
	case Json::Type::json_string:
		m_value.m_string = new std::string("");
		break;
	case Json::Type::json_array:
		m_value.m_array = new std::vector<Json>();
		break;
	case Json::Type::json_object:
		m_value.m_object = new std::map<std::string, Json>();
		break;
	default: 
		break;
	}
}


Json::Json(const Json& other)
{
	_Coyp(other);
}


Json::operator bool()
{
	if (m_type != Type::json_bool)
	{
		throw std::logic_error("type error, not bool value");
	}
	return m_value.m_bool;
}

Json::operator int()
{
	if (m_type != Type::json_int)
	{
		throw std::logic_error("type error, not int value");
	}
	return m_value.m_int;
}

Json::operator double()
{
	if (m_type != Type::json_double)
	{
		throw std::logic_error("type error, not double value");
	}
	return m_value.m_double;
}

Json::operator std::string()
{
	if (m_type != Type::json_string)
	{
		throw std::logic_error("type error, not string value");
	}
	return *m_value.m_string;
}

Json& Json::operator[](const int index)
{
	if (index < 0)
	{
		throw std::logic_error("array[] index < 0");
	}
	
	if (m_type != Type::json_array)
	{
		m_type = Type::json_array;
		m_value.m_array = new std::vector<Json>();
	}

	int size = (m_value.m_array)->size();
	if (index >= size)
	{
		//这里 size - index > 1 是否应该抛出异常
		for (int i = size; i <= index; ++i)
		{
			(m_value.m_array)->push_back(Json());
		}
	}

	return (*m_value.m_array).at(index);
}

Json& Json::operator[](const char* key)
{
	std::string name(key);
	return (*this)[name];
}

Json& Json::operator[](const std::string& key)
{
	if (m_type != Type::json_object)
	{
		Clear();
		m_type = Type::json_object;
		m_value.m_object = new std::map<std::string, Json>();
	}
	return (*(m_value.m_object))[key];
}

void Json::operator=(const Json& other)
{
	if (this == &other) return;

	Clear();
	_Coyp(other);
}

bool Json::operator==(const Json& other)
{
	if (this->m_type != other.m_type) return false;

	switch (m_type)
	{
	case Json::Type::json_null:
		return true;
	case Json::Type::json_bool:
		return m_value.m_bool == other.m_value.m_bool;
		break;
	case Json::Type::json_int:
		return m_value.m_int == other.m_value.m_int;
		break;
	case Json::Type::json_double:
		return m_value.m_double == other.m_value.m_double;
		break;
	case Json::Type::json_string:
		return *(m_value.m_string) == *(other.m_value.m_string);
		break;
	case Json::Type::json_array:
		return m_value.m_array == other.m_value.m_array; //***
		break;
	case Json::Type::json_object:
		return m_value.m_object == other.m_value.m_object; //***
		break;
	default:
		break;
	}

	return false;
}

bool Json::operator!=(const Json& other)
{
	return !(*this == other);
}

//数组追加元素
void Json::Append(const Json& other)
{
	if (m_type != Type::json_array)
	{
		Clear();
		m_type = Type::json_array;
		m_value.m_array = new std::vector<Json>();
	}

	(m_value.m_array)->push_back(other);
}

//以字符串的方式返回数据
std::string Json::Str() const
{
	std::stringstream ss;

	switch (m_type)
	{
	case Json::Type::json_null:
		ss << "null";
		break;
	case Json::Type::json_bool:
		if (m_value.m_bool)
		{
			ss << "true";
			break;
		}
		ss << "false";
		break;
	case Json::Type::json_int:
		ss << m_value.m_int;
		break;
	case Json::Type::json_double:
		ss << m_value.m_double;
		break;
	case Json::Type::json_string:
		ss << '\"' << *(m_value.m_string) << '\"';
		break;
	case Json::Type::json_array:
		{
			ss << '[';
			for (auto it = (m_value.m_array)->begin(); it != (m_value.m_array)->end(); ++it)
			{
				if (it != (m_value.m_array)->begin())
				{
					ss << ',';
				}
				ss << it->Str();
			}
			ss << ']';
		}
		break;
	case Json::Type::json_object:
		{
			ss << '{';
			for (auto it = (m_value.m_object)->begin(); it != (m_value.m_object)->end(); ++it)
			{
				if (it != (m_value.m_object)->begin())
				{
					ss << ',';
				}
				ss << '\"' << it->first << '\"' << ":" << it->second.Str();
			}
			ss << '}';
		}
		break;
	default:
		break;
	}

	return ss.str();
}


void Json::_Coyp(const Json& other)
{
	m_type = other.m_type;
	switch (m_type)
	{
	case Json::Type::json_null:
		break;
	case Json::Type::json_bool:
		m_value.m_bool = other.m_value.m_bool;
		break;
	case Json::Type::json_int:
		m_value.m_int = other.m_value.m_int;
		break;
	case Json::Type::json_double:
		m_value.m_double = other.m_value.m_double;
		break;
	case Json::Type::json_string:
		m_value.m_string = other.m_value.m_string;
		break;
	case Json::Type::json_array:
		m_value.m_array = other.m_value.m_array;
		break;
	case Json::Type::json_object:
		m_value.m_object = other.m_value.m_object;
		break;
	default:
		break;
	}
}


//清理
void Json::Clear()
{
	switch (m_type)
	{
	case Json::Type::json_null:
		break;
	case Json::Type::json_bool:
		m_value.m_bool = false;
		break;
	case Json::Type::json_int:
		m_value.m_int = 0;
		break;
	case Json::Type::json_double:
		m_value.m_double = 0.0;
		break;
	case Json::Type::json_string:
		{
			delete m_value.m_string;
		}
		break;
	case Json::Type::json_array:
		{
			for (auto it = m_value.m_array->begin(); it != m_value.m_array->end(); ++it)
			{
				it->Clear();
			}
			delete m_value.m_array;
		}
		break;
	case Json::Type::json_object:
		{
			for (auto it = m_value.m_object->begin(); it != m_value.m_object->end(); ++it)
			{
				it->second.Clear();
			}
			delete m_value.m_object;
		}
		break;
	default:
		break;
	}

	m_type = Type::json_null;
}

bool Json::AsBool() const
{
	if (m_type != Type::json_bool)
	{
		throw std::logic_error("type error, not bool value");
	}
	return m_value.m_bool;
}

int Json::AsInt() const
{
	if (m_type != Type::json_int)
	{
		throw std::logic_error("type error, not int value");
	}
	return m_value.m_int;
}

double Json::AsDouble() const
{
	if (m_type != Type::json_double)
	{
		throw std::logic_error("type error, not double value");
	}
	return m_value.m_double;
}

std::string Json::AsString() const
{
	if (m_type != Type::json_string)
	{
		throw std::logic_error("type error, not string value");
	}
	return (*m_value.m_string);
}


bool Json::Has(int index)
{
	if (m_type != Type::json_array)
	{
		return false;
	}

	return index >= 0 && index < (m_value.m_array)->size();
}

bool Json::Has(const char* key)
{
	return this->Has(std::string(key));
}

bool Json::Has(const std::string& key)
{
	if (m_type != Type::json_object)
	{
		return false;
	}
	return m_value.m_object->find(key) != m_value.m_object->end();
}


bool Json::Remove(int index)
{
	if (!this->Has(index)) return false;

	m_value.m_array->at(index).Clear();
	m_value.m_array->erase((m_value.m_array->begin() + index));
	return true;
}

bool Json::Remove(const char* key)
{
	return this->Remove(std::string(key));
}

bool Json::Remove(const std::string& key)
{
	if (m_type != Type::json_object)
	{
		return false;
	}
	auto it = m_value.m_object->find(key);

	if (it == m_value.m_object->end())
	{
		return false;
	}

	it->second.Clear();
	m_value.m_object->erase(it);
	return true;
}

Json::arrayIterator Json::Begin()
{
	if (m_type != Type::json_array)
	{
		throw std::logic_error("type error, not array value");
	}
	return m_value.m_array->begin();
}

Json::arrayIterator Json::End()
{
	if (m_type != Type::json_array)
	{
		throw std::logic_error("type error, not array value");
	}
	return m_value.m_array->end();
}